package org.springframework.context.event;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @author derekyi
 * @date 2020/12/5
 */
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
	//事件发布者内部有集合存所有事件监听器对象
	public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
		setBeanFactory(beanFactory);
	}

	@Override
	public void multicastEvent(ApplicationEvent event) {
		//这里集合是我们之前存入的3个事件监听器，如下循环
		for (ApplicationListener<ApplicationEvent> applicationListener : applicationListeners) {

			//这里循环的时候有一个关键的步骤，这个事件监听器是否是用于处理你传入的这个事件（event）的，通过泛型判断

			//进入判断方法看看
			if (supportsEvent(applicationListener, event)) {

				//如果成功判断就执行这个事件监听器内部重写的方法
				applicationListener.onApplicationEvent(event);
			}
		}
	}

	/**
	 * 监听器是否对该事件感兴趣
	 *
	 * @param applicationListener
	 * @param event
	 * @return
	 */
	//泛型的判断能力
	protected boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener, ApplicationEvent event) {
		//1.Class类是无敌的，啥都有。通过反射得到了第一个接口
		Type type = applicationListener.getClass().getGenericInterfaces()[0];
		//2.得到第一个接口里的第一个泛型，0是指泛型我们可以有多个，这样就是要第一个泛型
		Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0];

		//得到泛型的类名称
		String className = actualTypeArgument.getTypeName();
		Class<?> eventClassName;
		try {
			eventClassName = Class.forName(className);//得到具体的泛型类
		} catch (ClassNotFoundException e) {
			throw new BeansException("wrong event class name: " + className);
		}
		//最后做判断两个类型是否一致（Class类里的方法，底层）
		return eventClassName.isAssignableFrom(event.getClass());
	}
}
